<script setup lang="ts">
import type { Column, RowData } from './type.ts';
import { ref } from 'vue';
import { useColumnResize } from './composables/resizeModule';
import { tooltipModule } from './composables/tooltipModule';
import { useDragScroll } from './composables/dragScrollModule';

// 初始化tooltip模块
const tableRef = ref(null);
const { tooltip, showTooltip, hideTooltip } = tooltipModule();

// 导出事件类型
interface Emits {
  (e: 'rowClick', row: RowData, column: Column, event: Event): void;

  (e: 'rowDblclick', row: RowData, column: Column, event: Event): void;

  (e: 'cellClick', row: RowData, column: Column, cell: any, event: Event): void;

  (e: 'sortChange', column: Column, prop: string, order: 'ascending' | 'descending' | null): void;

  (e: 'currentChange', currentRow: RowData | null, oldCurrentRow: RowData | null): void;

  (e: 'columnResize', columnIndex: number, newWidth: number): void;

  (e: 'filterChange', column: Column, prop: string): void;
}

interface Props {
  data: RowData[];
  columns: Column[];
  rowHeight?: number; //表格高度
  headerHeight?: number; //表头高度
  loading?: boolean; //加载中
  loadingText?: string; //加载文本
  stripe?: boolean; //斑马纹
  dragScroll?: boolean; //点击表头滚动表格
  border?: boolean; //边框
  align?: 'left' | 'center' | 'right'; //对齐方式
  showHeader?: boolean; //显示表头
  emptyText?: string; //空数据提示
}

const props = withDefaults(defineProps<Props>(), {
  stripe: false,
  border: false,
  loading: false,
  dragScroll: false,
  filter: false,
  rowHeight: 35,
  headerHeight: 40,
  align: 'center',
  showHeader: true,
  emptyText: '暂无数据',
  loadingText: '正在加载数据'
});

// 拖拽状态
const dragState = ref({
  startX: 0,
  startY: 0,
  scrollTop: 0,
  scrollLeft: 0
});

// 排序状态
const sortState = ref<{
  columnIndex: number | null;
  order: 'ascending' | 'descending' | null;
}>({
  columnIndex: null,
  order: null
});

const emit = defineEmits<Emits>();
const localColumns = ref([...props.columns]);
// 计算表格宽度
const tableWidth = computed(() => {
  return tableRef.value?.clientWidth || 'auto';
});
// 使用拖拽调整列宽模块
const { handleResizeStart } = useColumnResize({
  tableRef,
  localColumns,
  emit
});

// 使用拖动滚动模块
const { handleHeaderMouseDown } = useDragScroll({
  tableRef
});

// 处理排序
const handleSort = (index: number, column: Column) => {
  // 如果点击的是同一列，则切换排序状态；否则重置为升序
  if (sortState.value.columnIndex === index) {
    switch (sortState.value.order) {
      case null:
        sortState.value.order = 'ascending';
        break;
      case 'ascending':
        sortState.value.order = 'descending';
        break;
      case 'descending':
        sortState.value.order = null;
        break;
    }
  } else {
    sortState.value.columnIndex = index;
    sortState.value.order = 'ascending';
  }

  emit('sortChange', column, column.prop, sortState.value.order);
};

// 处理筛选
const handleFilter = (index: number, column: Column) => {
  emit('filterChange', column, column.prop);
};
</script>

<template>
  <div class="table-wrapper" ref="tableRef" :class="{ 'drag-scroll-enabled': dragScroll }">
    <table class="table" :class="{ stripe, border }">
      <thead
        v-if="showHeader"
        class="thead"
        :style="{
          height: props.headerHeight + 'px'
        }"
      >
        <tr>
          <th
            v-for="(column, index) in localColumns"
            :key="index"
            :style="{
              width: (column.width || 100) + 'px',
              textAlign: align
            }"
            :class="{
              'drag-scroll-header': dragScroll,
              'sortable': column.sortable,
              'sorted': sortState.columnIndex === index && sortState.order !== null,
              'ascending': sortState.columnIndex === index && sortState.order === 'ascending',
              'descending': sortState.columnIndex === index && sortState.order === 'descending'
            }"
            @mousedown="dragScroll ? handleHeaderMouseDown($event) : () => {}"
          >
            <div class="header-content">
              <span class="header-label" @mouseenter="showTooltip($event, column.label)" @mouseleave="hideTooltip">
                {{ column.label }}
              </span>
              <div class="header-icons">
                <span v-if="column.sortable" class="sort-icon" @click.stop="handleSort(index, column)" title="排序">
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M12 5L19 12H5L12 5Z" fill="currentColor" />
                  </svg>
                </span>
                <span v-if="column.filterable" class="filter-icon" @click.stop="handleFilter(index, column)" title="筛选">
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M4 6H20M7 12H17M10 18H14" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
                  </svg>
                </span>
              </div>
              <div class="resize-handle" @mousedown.stop="handleResizeStart($event, index)" title="拖拽调整列宽" />
            </div>
          </th>
        </tr>
      </thead>
      <tbody v-if="data && data.length > 0">
        <tr v-for="(row, rowIndex) in data" :key="rowIndex">
          <td
            v-for="(column, colIndex) in localColumns"
            :key="colIndex"
            :style="{
              width: (column.width || 100) + 'px',
              textAlign: align,
              height: (rowHeight || 30) + 'px'
            }"
          >
            <div class="cell-content" @mouseenter="showTooltip($event, row[column.prop])" @mouseleave="hideTooltip">
              {{ row[column.prop] }}
            </div>
          </td>
        </tr>
      </tbody>
      <tbody v-else>
        <tr>
          <td :colspan="localColumns.length" class="empty-placeholder-cell">
            <!-- Loading 遮罩 -->
            <div v-if="loading" class="empty-overlay" :style="{ width: tableWidth === 'auto' ? '100%' : tableWidth + 'px' }">
              <div class="loading-spinner"></div>
              <div class="loading-text">{{ loadingText }}</div>
            </div>
            <!-- 空状态提示 -->
            <div v-else :style="{ width: tableWidth === 'auto' ? '100%' : tableWidth + 'px' }">
              {{ emptyText }}
            </div>
          </td>
        </tr>
      </tbody>
    </table>
    <!-- Tooltip 提示框 -->
    <div
      v-if="tooltip.visible"
      class="custom-tooltip"
      :style="{
        left: tooltip.x + 'px',
        top: tooltip.y + 'px'
      }"
    >
      {{ tooltip.content }}
    </div>
  </div>
</template>

<style lang="less" scoped>
@table-bg-color: #ffffff; // 表格背景色
@table-text-color: #606266; // 文字颜色
@table-border-color: rgba(207, 205, 205, 0.47); // 表格边框颜色
@table-stripe-bg-color: #f0f0f0; // 斑马纹背景色
@table-header-bg-color: #f5f7fa; // 表头背景色
@table-header-text-color: #909399; // 表头文字颜色
@resize-handle-hover-color: #409eff; // 调整列宽

.table-wrapper {
  overflow: auto;
  position: relative;
  background-color: @table-bg-color;
  width: 100%;
  max-height: 100%;

  &:focus {
    outline: none;
  }
}

.table {
  border-collapse: collapse;
  table-layout: fixed;
  width: 100%;
  min-width: 100%;

  &.stripe tbody tr:nth-child(even) td {
    background-color: @table-stripe-bg-color;
  }

  &.border th,
  &.border td {
    border: 1px solid @table-border-color;
  }
}

.thead {
  position: sticky;
  top: 0;
  left: 0;
  z-index: 1;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  display: table-row-group;
}

th,
td {
  position: relative;
  font-size: 14px;
  border: 1px solid @table-border-color;
  box-sizing: border-box;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

th {
  background-color: @table-header-bg-color;
  text-align: center;
  user-select: none;
  height: 40px;
  display: table-cell;
  position: relative;
  padding: 0 4px;

  .header-content {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 100%;
    width: 100%;
    box-sizing: border-box;
  }

  .header-label {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: center;
  }

  .sort-icon,
  .filter-icon {
    opacity: 0.4;
    transition: all 0.2s ease;
    min-width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #606266;

    &:hover {
      opacity: 0.8;
      background-color: rgba(0, 0, 0, 0.05);
      border-radius: 2px;
    }

    &:active {
      opacity: 1;
      background-color: rgba(0, 0, 0, 0.1);
    }

    svg {
      width: 12px;
      height: 12px;
    }
  }

  &.sortable .header-label {
    cursor: pointer;
  }

  &.sortable:hover .sort-icon {
    opacity: 0.6;
  }

  &.sorted .sort-icon {
    opacity: 1;
    color: #409eff;
  }

  &.ascending .sort-icon svg {
    transform: rotate(0deg);
  }

  &.descending .sort-icon svg {
    transform: rotate(180deg);
  }

  .resize-handle {
    position: absolute;
    right: 0;
    top: 0;
    width: 3px;
    height: 100%;
    cursor: col-resize;
    z-index: 1;
  }
}

th .resize-handle:hover {
  background-color: @resize-handle-hover-color;
}

td {
  background-color: @table-bg-color;
  text-align: center;
  display: table-cell;

  .cell-content {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: normal;
    font-size: 14px;
    color: @table-text-color;
  }
}

/* Tooltip 样式 */
.custom-tooltip {
  position: fixed;
  background-color: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 6px 10px;
  border-radius: 4px;
  font-size: 12px;
  white-space: nowrap;
  z-index: 1000;
  pointer-events: none;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
  transition: opacity 0.2s ease-out;
}

// 添加空占位单元格样式
.empty-placeholder-cell {
  position: relative;
  height: 150px;
  width: 100%;
}

.empty-overlay {
  position: absolute;
  top: 0;
  left: 0;
  // 加载动画
  .loading-spinner {
    width: 40px;
    height: 40px;
    border: 4px solid rgba(64, 158, 255, 0.2);
    border-top: 4px solid #409eff;
    border-radius: 50%;
    animation: spin 0.8s cubic-bezier(0.68, -0.55, 0.27, 1.55) infinite;
    margin: 0 auto 16px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }

  // 加载文字
  .loading-text {
    color: #606266;
    font-weight: 500;
    font-size: 15px;
    letter-spacing: 0.5px;
  }

  .empty-content {
    background: white;
    padding: 24px;
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
    pointer-events: auto;

    &::before {
      content: '';
      display: block;
      width: 64px;
      height: 64px;
      margin: 0 auto 16px;
      background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23409eff'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm-1-6h2v2h-2zm0-8h2v6h-2z'/%3E%3C/svg%3E")
        no-repeat center;
      background-size: contain;
    }
  }

  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
}
</style>
